#!/bin/bash
 #=================== SYSTEM ===================#
  SYSTEMD="/root/print3D"
  INITD="/etc/init.d"
  ETCDEF="/etc/default"
  DATABK="/root/printer_data"
  DATABK1="/home/print3D/printer_data"
  #PIP3YUAN="https://pypi.mirrors.ustc.edu.cn/simple/"
  PIP3YUAN="https://pypi.tuna.tsinghua.edu.cn/simple"
  #PIP3YUAN="http://pypi.hustunique.com/"
  #PIP3YUAN="http://pypi.sdutlinux.org/"
  #PIP3YUAN="http://pypi.douban.com/simple/"
  #PIP3YUAN="https://mirrors.aliyun.com/pypi/simple"
  #=================== KIAUH ==================#
### sourcing all additional scripts
  KIAUH_SRCDIR="/home/print3D/kiauh"
  KIAUH_REPO="https://gitee.com/miroky/kiauh.git"
  green=$(echo -en "\e[92m")
  yellow=$(echo -en "\e[93m")
  magenta=$(echo -en "\e[35m")
  red=$(echo -en "\e[91m")
  cyan=$(echo -en "\e[96m")
  white=$(echo -en "\e[39m")
  home1="/home/print3D"
  INI_FILE="/home/print3D/kiauh.ini"
  LOGFILE="/tmp/kiauh.log"
  RESOURCES="${KIAUH_SRCDIR}/resources"
  BACKUP_DIR="/home/print3D/kiauh-backups"
  #=====================PIP======================#
  # for using official pip source, comment next line
  PIP_MIRROR="https://pypi.tuna.tsinghua.edu.cn/simple"
  #================== KLIPPER ===================#
  KLIPPY_ENV="/home/print3D/klippy-env"
  KLIPPER_DIR="/home/print3D/klipper"
  KLIPPER_REPO="https://gitee.com/miroky/klipper.git"
  KLIPPER_TXT="/home/print3D/klipper/scripts/klippy-requirements.txt"
  #================= MOONRAKER ==================#
  MOONRAKER_ENV="/home/print3D/moonraker-env"
  MOONRAKER_DIR="/home/print3D/moonraker"
  MOONRAKER_REPO="https://gitee.com/miroky/moonraker.git"
  MOONRAKER_TXT="/home/print3D/moonraker/scripts/moonraker-requirements.txt"
  #================= PolicyKit ==================#
  POLKIT_LEGACY_DIR="/etc/polkit-1/localauthority/50-local.d"
  POLKIT_DIR="/etc/polkit-1/rules.d"
  POLKIT_USR_DIR="/usr/share/polkit-1/rules.d"
  MOONRAKER_UNIT="/etc/init.d/moonraker"
  MOONRAKER_GID="-1"
  #================= MAINSAIL ===================#
  MAINSAIL_DIR="/home/print3D/mainsail"
  MAINSAIL_REPO_API="https://gitee.com/Neko-vecter/mainsail-releases/raw/main/mainsail-res"
  MAINSAIL_TAGS="https://gitee.com/Neko-vecter/mainsail-releases/raw/main/Neko-mainsail-res"
  MAINSAIL_MACRO="https://gitee.com/Neko-vecter/mainsail-releases/raw/main/klipper_config/mainsail.cfg"
  #================== FLUIDD ====================#
  FLUIDD_DIR="/home/print3D/fluidd"
  FLUIDD_REPO_API="https://gitee.com/Neko-vecter/fluidd-releases/raw/main/fluidd-res"
  FLUIDD_TAGS="https://gitee.com/Neko-vecter/fluidd-releases/raw/main/Neko-fluidd-res"
  FLUIDD_MACRO="https://gitee.com/Neko-vecter/fluidd-releases/raw/main/klipper_config/fluidd.cfg"
  NGINX_SA="/etc/nginx/sites-available"
  NGINX_SE="/etc/nginx/sites-enabled"
  NGINX_CONFD="/etc/nginx/conf.d"
  #=============== KLIPPERSCREEN ================#
  KLIPPERSCREEN_ENV="/home/print3D/KlipperScreen-env"
  KLIPPERSCREEN_DIR="/home/print3D/KlipperScreen"
  KLIPPERSCREEN_REPO="https://gitee.com/Neko-vecter/KlipperScreen.git"
  KLIPPERSCREEN_TXT="/home/print3D/KlipperScreen/scripts/KlipperScreen-requirements.txt"
#=================================================#
#================ INSTALL KLIPPER ================#
#=================================================#
[[ -d ${KIAUH_SRCDIR} ]] && rm -rf "${KIAUH_SRCDIR}"
git clone ${KIAUH_REPO} ${KIAUH_SRCDIR}

function run_klipper_setup() {
  chmod 4755 /bin/busybox

  ### step 1:克隆klipper
  clone_klipper
  ### step 2: 安装klipper依赖项并创建python-virtualenv
  install_klipper_packages
  create_virtualenv "${KLIPPY_ENV}" "${KLIPPER_TXT}"
  ### step 3: 创建klipper实例
  create_required_folders "${DATABK1}"
  create_required_folders "${DATABK1}"
  write_example_printer_cfg "${DATABK1}/config/printer.cfg"
  install_script_klipper
  install_config_klipper
  ### step 4: 启用并启动所有实例
  #start_software_klipper
  status_msg "klipper安装完成！"
}
function clone_klipper() {
  local repo="${KLIPPER_REPO}"
  local branch="master"
  if [[ ${repo} =~ .*"github.com".* ]] || [[ ! ${repo} =~ ^"http".* ]]; then
    repo=$(echo "${repo}" | sed -r "s/^(http|https):\/\/github\.com\///i; s/\.git$//")
    repo="https://github.com/${repo}"
  fi
  ### 强制删除现有的klipper目录并克隆到新的klippr目录
  [[ -d ${KLIPPER_DIR} ]] && rm -rf "${KLIPPER_DIR}"

  status_msg "从${repo}克隆Klipper ..."

  if  git clone "${repo}" "${KLIPPER_DIR}"; then
    cd "${KLIPPER_DIR}" && git checkout "${branch}"
  else
    print_error "从${repo}克隆Klipper失败!"
  fi
}
function install_klipper_packages() {
  ### 更新系统包信息
  status_msg "正在更新程序包列表..."
  if ! apk update ; then
    log_error "更新程序包列表时失败"
    error_msg "更新程序包列表失败"
  fi
  ### 安装所需的程序包
  status_msg "正在安装所需的依赖..."
  su-exec print3D pip3 install python-can  -i https://pypi.tuna.tsinghua.edu.cn/simple
  su-exec print3D pip3 install virtualenv -i https://pypi.tuna.tsinghua.edu.cn/simple
  su-exec print3D pip3 install pyserial -i https://pypi.tuna.tsinghua.edu.cn/simple
}
# Step 3: 安装启动脚本
function install_script_klipper(){
    status_msg "正在安装系统启动脚本..."
    cp "${KIAUH_SRCDIR}/resources/klipper.env" "${DATABK1}/systemd/klipper.env"
    sed -i "s|%USER%|print3D|; s|%PRINTER_DATA%|${DATABK1}|" "${DATABK1}/systemd/klipper.env"
  
    chmod +x /etc/init.d/klipper
    chmod 777 /etc/init.d/klipper
    #rc-update add klipper defaults 80 20
}
# Step 4: 安装启动脚本配置
function install_config_klipper(){
    DEFAULTS_FILE=/etc/default/klipper
        mkdir -p /etc/default
        status_msg  "正在安装系统启动配置..."
        cat > ${DEFAULTS_FILE} <<EOF
    # Configuration for /etc/init.d/klipper
    KLIPPY_USER=root
    KLIPPY_EXEC=/home/print3D/klippy-env/bin/python
    KLIPPY_ARGS="/home/print3D/klipper/klippy/klippy.py ${DATABK1}/config/printer.cfg -I ${DATABK1}/comms/klippy.serial -l  ${DATABK1}/logs/klippy.log -a ${DATABK1}/comms/klippy_uds"

EOF
}
# Step 5:启动主机软件
function start_software_klipper(){
    status_msg "启动Klipper主机软件..."
    rc-service klipper start
}
function write_example_printer_cfg() {
  local cfg=${1}
  local cfg_template="${KIAUH_SRCDIR}/resources/example.printer.cfg"
  status_msg "创建最小示例printer.cfg ..."
  if  cp "${cfg_template}" "${cfg}"; then
    ok_msg "创建的最小示例printer.cfg!"
  else
    error_msg "无法创建最小示例printer.cfg!"
  fi
}
function create_required_folders() {
  local printer_data=${1} folders
  folders=("backup" "certs" "config" "database" "gcodes" "comms" "logs" "systemd")
  for folder in "${folders[@]}"; do
    local dir="${printer_data}/${folder}"

    ### 删除moonraker可能创建的符号链接
    if [[ -L "${dir}" && -d "${dir}" ]]; then
      rm "${dir}"
    fi

    if [[ ! -d "${dir}" ]]; then
      status_msg "正在创建文件夹 '${dir}' ..."
      mkdir -p "${dir}"
      ok_msg "已创建文件夹 '${dir}' !"
    fi
  done
}
#=================================================#
#================ INSTALL MOONRAKER ================#
#=================================================#
function moonraker_setup() {
  local instance_arr="print3D"
  ### step 1: 克隆 moonraker
  clone_moonraker
  ### step 2: 安装moonraker依赖项并创建python-virtualenv
  status_msg "正在安装依赖项 ..."
  install_moonraker_dependencies
  create_virtualenv "${MOONRAKER_ENV}" "${MOONRAKER_TXT}"
  ### step 3: 创建moonraker.conf
  #create_moonraker_conf
  ### step 4: 创建moonraker实例
  install_script_moonraker
  install_config_moonraker
  ### step 5: 为moonraker创建polkit规则
  #install_moonraker_polkit || true
  #start_software_moonraker
  status_msg "moonraker安装完成！"
}
function install_moonraker_dependencies() {
  status_msg "正在更新程序包列表..."
  if ! apk update ; then
    log_error "更新程序包列表时失败"
    error_msg "更新程序包列表失败!"
    exit 1
  fi

}

function clone_moonraker() {
  status_msg "从克隆Moonraker ${repo} ..."
  ### 强制删除现有的moonraker目录并克隆到新的moonroker目录
  [[ -d ${MOONRAKER_DIR} ]] && rm -rf "${MOONRAKER_DIR}"
  if ! git clone "${MOONRAKER_REPO}" "${MOONRAKER_DIR}"; then
    print_error "从克隆Moonraker\n ${repo}\n 失败的!"
    exit 1
  fi
  #sed -i '/fm.check_write_enabled/d'  /home/print3D/moonraker/moonraker/app.py
  sed -i  's/max_dbs=MAX_NAMESPACES/&, lock=False/' /home/print3D/moonraker/moonraker/components/database.py
  sed -i  's/command -v apt/command -v apk/' /home/print3D/moonraker/moonraker/components/update_manager/update_manager.py
  sed -i  's/apt-cache search --names-only/ apk add /' /home/print3D/moonraker/moonraker/components/update_manager/update_manager.py
  sed -i  's/apt list --upgradable/ apk search --update /' /home/print3D/moonraker/moonraker/components/update_manager/update_manager.py
  sed -i  's/install --yest/add/' /home/print3D/moonraker/moonraker/components/update_manager/update_manager.py
  sed -i  's/upgrade --yes/upgrade/' /home/print3D/moonraker/moonraker/components/update_manager/update_manager.py
  #sed -i -e '$!N;/\n.*Path not available for DELETE:/!P;D'  /home/print3D/moonraker/moonraker/components/file_manager/file_manager.py
  sed -i "s/self.full_access_roots.clear()/self.full_access_roots/" /home/print3D/moonraker/moonraker/components/file_manager/file_manager.py
  #sed -i "/Invalid root request:/c\                    self.full_access_roots.add\(\'config\'\)\n                    self.full_access_roots.add\(\'gcodes\'\)" /home/print3D/moonraker/moonraker/components/file_manager/file_manager.py
  #sed -i -e '/DBus Connection Not available, systemd/{n;d}' -e '$!N;/\n.*DBus Connection Not available, systemd/!P;D'  /home/print3D/moonraker/moonraker/components/machine.py
  #sed -i '/DBus Connection Not available, systemd/d'  /home/print3D/moonraker/moonraker/components/machine.py
  sed -i '/print3D ALL=(ALL) NOPASSWD:ALL/a\nginx ALL=(ALL) NOPASSWD:ALL'  /etc/sudoers
  sed -i '/nginx ALL=(ALL) NOPASSWD:ALL/a\messagebus ALL=(ALL) NOPASSWD:ALL'  /etc/sudoers
  addgroup -g 10001 -S moonraker-admin
  adduser  root  moonraker-admin
  adduser  print3D  moonraker-admin
  adduser  nginx  moonraker-admin
  adduser  messagebus  moonraker-admin
  adduser  print3D  root
  adduser  nginx  root
  adduser  messagebus  root
  rc-update add dbus
}
function create_moonraker_conf() {
  local input="print3D"
  local names=("${input}") && unset "input"
  local port lan printer_data cfg_dir cfg uds
  port=7125
  lan="$(hostname -i | cut -d" " -f1 | cut -d"." -f1-2).0.0/16"
  printer_data="${DATABK1}"
  cfg_dir="${printer_data}/config"
  cfg="${cfg_dir}/moonraker.conf"
  uds="${DATABK1}/comms/klippy_uds"
  
  ### 写入单实例配置
  write_moonraker_conf "${cfg_dir}" "${cfg}" "${port}" "${uds}" "${lan}" 
}
function write_moonraker_conf() {
  local cfg_dir=${1} cfg=${2} port=${3} uds=${4} lan=${5}  
  local conf_template="${KIAUH_SRCDIR}/resources/moonraker.conf"
  [[ ! -d ${cfg_dir} ]] && mkdir -p "${cfg_dir}"
  if [[ ! -f ${cfg} ]]; then
    status_msg "在中创建moonraker.conf ${cfg_dir} ..."
    cp "${conf_template}" "${cfg}"
    sed -i "s|%USER%|${USER}|g; s|%PORT%|${port}|; s|%UDS%|${uds}|" "${cfg}"
    #如果主机ip不在默认ip范围内，则替换占位符，
    #否则，从配置中删除占位符
    if ! grep -q "${lan}" "${cfg}"; then
      sed -i "s|%LAN%|${lan}|" "${cfg}"
    else
      sed -i "/%LAN%/d" "${cfg}"
    fi
    ok_msg "moonraker.conf已创建!"
  else
     status_msg "文件 '${cfg_dir}/moonraker.conf已经存在！ \n跳过..."
  fi
    
}
function install_script_moonraker(){
    status_msg "正在安装系统启动脚本..."
    cp "${KIAUH_SRCDIR}/resources/moonraker.env" "${DATABK1}/systemd/moonraker.env"
    sed -i "s|%USER%|print3D|; s|%PRINTER_DATA%|${DATABK1}|" "${DATABK1}/systemd/moonraker.env"
  
    chmod +x /etc/init.d/moonraker
    chmod 777 /etc/init.d/moonraker
    #rc-update add moonraker defaults 90 10
}
function install_config_moonraker(){
  chmod -R 777 ${DATABK1}
  chmod -R 777 ${DATABK1}
    DEFAULTS_FILE=/etc/default/moonraker
        status_msg  "正在安装系统启动配置..."
        cat > ${DEFAULTS_FILE} <<EOF
    # Configuration for /etc/init.d/moonraker
    MOONRAKER_USER=root
    MOONRAKER_EXEC=/home/print3D/moonraker-env/bin/python
    MOONRAKER_ARGS="/home/print3D/moonraker/moonraker/moonraker.py -c ${DATABK1}/config/moonraker.conf -l ${DATABK1}/logs/moonraker.log -d ${DATABK1}"

EOF
}
function start_software_moonraker(){

    status_msg "启动moonraker服务..."
    rc-service moonraker start
}
function install_moonraker_polkit() {

  local POLKIT_LEGACY_FILE="/etc/polkit-1/localauthority/50-local.d/10-moonraker.pkla"
  local POLKIT_FILE="/etc/polkit-1/rules.d/moonraker.rules"
  local POLKIT_USR_FILE="/usr/share/polkit-1/rules.d/moonraker.rules"
  local legacy_file_exists
  local file_exists
  local usr_file_exists
  legacy_file_exists=$(find "${POLKIT_LEGACY_FILE}" 2> /dev/null)
  file_exists=$(find "${POLKIT_FILE}" 2> /dev/null)
  usr_file_exists=$(find "${POLKIT_USR_FILE}" 2> /dev/null)
  ### 仅当规则文件不存在时才执行moonrakers policykit规则脚本
  if [[ -z ${legacy_file_exists} && ( -z ${file_exists} || -z ${usr_file_exists} ) ]]; then
    status_msg "正在安装Moonraker policykit规则 ..."
    add_polkit_rules
    ok_msg "已安装Moonraker policykit规则!"
  fi

  return
}
function add_polkit_legacy_rules(){
    addgroup  moonraker-admin
    RULE_FILE="${POLKIT_LEGACY_DIR}/10-moonraker.pkla"
    report_status "安装Moonraker PolicyKit规则 (Legacy) to ${RULE_FILE}..."
    ACTIONS="org.freedesktop.systemd1.manage-units"
    ACTIONS="${ACTIONS};org.freedesktop.login1.power-off"
    ACTIONS="${ACTIONS};org.freedesktop.login1.power-off-multiple-sessions"
    ACTIONS="${ACTIONS};org.freedesktop.login1.reboot"
    ACTIONS="${ACTIONS};org.freedesktop.login1.reboot-multiple-sessions"
    ACTIONS="${ACTIONS};org.freedesktop.login1.halt"
    ACTIONS="${ACTIONS};org.freedesktop.login1.halt-multiple-sessions"
    ACTIONS="${ACTIONS};org.freedesktop.packagekit.*"
    sudo /bin/sh -c "cat > ${RULE_FILE}" << EOF
[moonraker permissions]
Identity=unix-user:$USER
Action=$ACTIONS
ResultAny=yes
EOF
}
function add_polkit_rules(){
    if [ ! -x "$(command -v pkaction)" ]; then
        echo "未安装PolicyKit"
        exit 1
    fi
    RULE_FILE=""
    if [ -d $POLKIT_USR_DIR ]; then
        RULE_FILE="${POLKIT_USR_DIR}/moonraker.rules"
    elif [ -d $POLKIT_DIR ]; then
        RULE_FILE="${POLKIT_DIR}/moonraker.rules"
    else
        echo "未检测到PolicyKit规则文件夹"
        exit 1
    fi
    report_status "正在将PolicyKit规则安装到 ${RULE_FILE}..."
    MOONRAKER_GID=$( getent group moonraker-admin | awk -F: '{printf "%d", $3}' )
     /bin/sh -c "cat > ${RULE_FILE}" << EOF
# 允许Moonraker用户管理系统设备、重新启动和关闭
# the system
polkit.addRule(function(action, subject) {
    if ((action.id == "org.freedesktop.systemd1.manage-units" ||
         action.id == "org.freedesktop.login1.power-off" ||
         action.id == "org.freedesktop.login1.power-off-multiple-sessions" ||
         action.id == "org.freedesktop.login1.reboot" ||
         action.id == "org.freedesktop.login1.reboot-multiple-sessions" ||
         action.id == "org.freedesktop.login1.halt" ||
         action.id == "org.freedesktop.login1.halt-multiple-sessions" ||
         action.id.startsWith("org.freedesktop.packagekit.")) &&
        subject.user == "$USER") {
        # Only allow processes with the "moonraker-admin" supplementary group
        # access
        var regex = "^Groups:.+?\\\s${MOONRAKER_GID}[\\\s\\\0]";
        var cmdpath = "/proc/" + subject.pid.toString() + "/status";
        try {
            polkit.spawn(["grep", "-Po", regex, cmdpath]);
            return polkit.Result.YES;
        } catch (error) {
            return polkit.Result.NOT_HANDLED;
        }
    }
});
EOF
}
function clear_polkit_rules(){
    report_status "删除所有Moonraker PolicyKit规则"
    sudo rm -f "${POLKIT_LEGACY_DIR}/10-moonraker.pkla"
    sudo rm -f "${POLKIT_USR_DIR}/moonraker.rules"
    sudo rm -f "${POLKIT_DIR}/moonraker.rules"
}
#===================================================#
#================== INSTALL FLUIDD =================#
#===================================================#
function install_fluidd() {
  ### 检测冲突的Haproxy和Apache2安装
  status_msg "正在初始化Fluidd安装 ..."
  mkdir -p /etc/nginx/conf.d
  mkdir -p /etc/nginx/sites-available
  mkdir -p /etc/nginx/sites-enabled
  sed -i '/\/etc\/nginx\/http.d\/\*.conf;/a\        include \/etc\/nginx\/sites-enabled\/\*;'  /etc/nginx/nginx.conf
  sed -i 's/http.d/conf.d/g' /etc/nginx/nginx.conf
  ### 下载fluidd
  download_fluidd
  ### 创造 /etc/nginx/conf.d/upstreams.conf
  #set_upstream_nginx_cfg
  ### 创造 /etc/nginx/sites-available/<interface config>
  set_nginx_cfg "fluidd"
  ### ubuntu 21及以上版本上的nginx需要特殊权限才能访问这些文件
  set_nginx_permissions
  ### 符号链接nginx日志
  symlink_webui_nginx_log "fluidd"
  ### 要求用户安装推荐的Web界面宏
  download_fluidd_macros
  ### 确认消息
  print_confirm "Fluidd已设置!"
}
function download_fluidd() {
  local url
  url=$(get_fluidd_download_url)

  status_msg "正在${url}从下载Fluidd  ..."

  if [[ -d ${FLUIDD_DIR} ]]; then
    rm -rf "${FLUIDD_DIR}"
  fi

  mkdir "${FLUIDD_DIR}" && cd "${FLUIDD_DIR}"

  if wget "${url}"; then
    ok_msg "下载完成!"
    status_msg "正在提取存档 ..."
    unzip -q -o ./*.zip && ok_msg "Done!"
    status_msg "删除下载的存档 ..."
    rm -rf ./*.zip && ok_msg "Done!"
  else
    print_error "下载 Fluidd from\n ${url}\n failed!"
    exit 1
  fi
}
function get_fluidd_download_url() {
  local tags latest_tag latest_url stable_tag stable_url url
  tags=$(curl -s "${FLUIDD_TAGS}" | grep "name" | cut -d'"' -f4)
  download_url=$(curl -s "${FLUIDD_TAGS}" | grep "download_url" | cut -d'"' -f4)
  # 获取最新标签和url
  latest_tag=$(echo "${tags}" | head -1)
  latest_url=$(echo "${download_url}" | head -1)
  url="${latest_url}"
  echo "${url}"
}
function set_upstream_nginx_cfg() {
  local upstreams="${NGINX_CONFD}/upstreams.conf"
  local common_vars="${NGINX_CONFD}/common_vars.conf"
  ### 将nginx配置复制到目标目标
  [[ ! -f ${upstreams} ]] &&  cp "${RESOURCES}/upstreams.conf" "${upstreams}"
  [[ ! -f ${common_vars} ]] &&  cp "${RESOURCES}/common_vars.conf" "${common_vars}"
}
function set_nginx_cfg() {
  local interface=${1}
    #检查相关性
    local cfg_src="${RESOURCES}/${interface}"
    local cfg_dest="/etc/nginx/sites-available/${interface}"
    status_msg "正在为创建NGINX配置 ${interface^} ..."
    # 将配置复制到目标并设置正确的用户名
    [[ -f ${cfg_dest} ]] &&  rm -rf "${cfg_dest}"
    cp "${cfg_src}" "${cfg_dest}"
    sed -i "/root/s/pi/print3D/" "${cfg_dest}"
    if [[ ${interface} == "fluidd" ]]; then
       sed -i "s/listen\s[0-9]*;/listen 8080;/" "${cfg_dest}"
       sed -i "s/listen\s\[\:*\]\:[0-9]*;/listen \[::\]\:8080;/" "${cfg_dest}"
       sed -i 's/http:\/\/apiserver/http:\/\/127.0.0.1:7125/g' "${cfg_dest}"
       sed -i 's/mjpgstreamer1/127.0.0.1:8080/g' "${cfg_dest}"
       sed -i 's/mjpgstreamer2/127.0.0.1:8081/g' "${cfg_dest}"
       sed -i 's/mjpgstreamer3/127.0.0.1:8082/g' "${cfg_dest}"
       sed -i 's/mjpgstreamer4/127.0.0.1:8083/g' "${cfg_dest}"
       ok_msg "${interface^} 为端口配置 8080!"
    else
       sed -i "s/listen\s[0-9]*;/listen 8081;/" "${cfg_dest}"
       sed -i "s/listen\s\[\:*\]\:[0-9]*;/listen \[::\]\:8081;/" "${cfg_dest}"
       sed -i 's/http:\/\/apiserver/http:\/\/127.0.0.1:7125/g' "${cfg_dest}"
       sed -i 's/mjpgstreamer1/127.0.0.1:8080/g' "${cfg_dest}"
       sed -i 's/mjpgstreamer2/127.0.0.1:8081/g' "${cfg_dest}"
       sed -i 's/mjpgstreamer3/127.0.0.1:8082/g' "${cfg_dest}"
       sed -i 's/mjpgstreamer4/127.0.0.1:8083/g' "${cfg_dest}"
       ok_msg "${interface^} 为端口配置 8081!"
    fi
    #删除nginx默认配置
    if [[ -e "/etc/nginx/sites-enabled/default" ]]; then
      rm "/etc/nginx/sites-enabled/default"
    fi

    #为自己的站点创建符号链接
    if [[ ! -e "/etc/nginx/sites-enabled/${interface}" ]]; then
       ln -s "/etc/nginx/sites-available/${interface}" "/etc/nginx/sites-enabled/"
    fi
    ok_msg "NGINX 的配置 ${interface^} 已设置!"

}
function set_nginx_permissions() {
  local homedir_perm
  local exec_perms_count
  homedir_perm=$(ls -ld "${home}/home/print3D")
  exec_perms_count=$(echo "${homedir_perm}" | cut -d" " -f1 | grep -c "x")
  if (( exec_perms_count < 3 )); then
    status_msg "授予NGINX所需的权限 ..."
    chmod og+x "${home}/home/print3D" && ok_msg "Done!"
  fi
  return
}
function symlink_webui_nginx_log() {
  local interface path access_log error_log regex logpaths
  interface=${1}
  access_log="/var/log/nginx/${interface}-access.log"
  error_log="/var/log/nginx/${interface}-error.log"
  path="${DATABK1}/log"
    [[ ! -d ${path} ]] && mkdir -p "${path}"
    if [[ -f ${access_log} && ! -L "${path}/${interface}-access.log" ]]; then
      status_msg "正在为 ${access_log}创建链接 ..."
      ln -s "${access_log}" "${path}"
      ok_msg "Symlink已创建: ${path}/${interface}-access.log"
    fi
    if [[ -f ${error_log} && ! -L "${path}/${interface}-error.log" ]]; then
      status_msg "正在为  ${error_log}创建链接 ..."
      ln -s "${error_log}" "${path}"
      ok_msg "Symlink已创建: ${path}/${interface}-error.log"
    fi

}
function download_fluidd_macros() {
  local fluidd_cfg path line gcode_dir
  path=${DATABK1}/config
  status_msg "克隆fluidd配置 ..."
  wget ${FLUIDD_MACRO} -P "${path}";
  if ! grep -Eq "^\[include fluidd.cfg\]$" "${path}/printer.cfg"; then
    log_info "${path}/printer.cfg"
    sed -i "1 i [include fluidd.cfg]" "${path}/printer.cfg"
    sed -i "/serial:/c serial: /dev/ttyOcto4a \n \#baud: 115200 \#\(非必须，默认波特率连不上可改为115200\) " "${path}/printer.cfg"
  fi
  line="$(($(grep -n "\[include fluidd.cfg\]" "${path}/printer.cfg" | tail -1 | cut -d: -f1) + 1))"
  gcode_dir="${DATABK1}/gcodes"
  if ! grep -Eq "^\[virtual_sdcard\]$" "${path}/fluidd.cfg"; then
    log_info "${path}/fluidd.cfg"
    sed -i "${line} i \[virtual_sdcard]\n path: ${gcode_dir}\n on_error_gcode: CANCEL_PRINT\n" "${path}/fluidd.cfg"
  fi
  #patch_fluidd_update_manager
  ok_msg "Done!"
}
function patch_fluidd_update_manager() {
 local conf="${DATABK1}/config/moonraker.conf"
    if ! grep -Eq "^\[update_manager fluidd\]\s*$" "${conf}"; then
      ### add new line to conf if it doesn't end with one
      [[ $(tail -c1 "${conf}" | wc -l) -eq 0 ]] && echo "" >> "${conf}"
      ### add Fluidds update manager section to moonraker.conf
      status_msg "将Fluidd添加到文件中的更新管理器:\n ${conf}"
      /bin/sh -c "cat >> ${conf}" << MOONRAKER_CONF

[update_manager fluidd]
type: web
channel: stable
repo: fluidd-core/fluidd
path: /home/print3D/fluidd
MOONRAKER_CONF

    fi
}
function install_script_nginx(){
    
    chmod +x /etc/init.d/nginxk
    chmod 777 /etc/init.d/nginxk
}
#===================================================#
#================= INSTALL MAINSAIL ================#
#===================================================#
function install_mainsail() {
  status_msg "正在初始化mainsail安装 ..."
  download_mainsail
  set_nginx_cfg "mainsail"
  symlink_webui_nginx_log "mainsail"
  download_mainsail_macros
  install_script_nginx
  print_confirm "mainsail已设置!"
}
function download_mainsail() {
  local url
  url=$(get_mainsail_download_url)
  status_msg "正在从 ${url} ..."
  if [[ -d ${MAINSAIL_DIR} ]]; then
    rm -rf "${MAINSAIL_DIR}"
  fi
  mkdir "${MAINSAIL_DIR}" && cd "${MAINSAIL_DIR}"

  if wget "${url}"; then
    ok_msg "下载完成!"
    status_msg "Extracting archive ..."
    unzip -q -o ./*.zip && ok_msg "Done!"
    status_msg "正在提取存档 ..."
    rm -rf ./*.zip && ok_msg "Done!"
  else
    print_error "正在从\n ${url}\n 失败!"
    exit 1
  fi
}
function get_mainsail_download_url() {
  local ms_tags tags latest_tag latest_url stable_tag stable_url url
  tags=$(curl -s "${MAINSAIL_TAGS}" | grep "name" | cut -d'"' -f4)
  download_url=$(curl -s "${MAINSAIL_TAGS}" | grep "download_url" | cut -d'"' -f4)
  # 获取最新标签和url
  latest_tag=$(echo "${tags}" | head -1)
  latest_url=$(echo "${download_url}" | head -1)
  url="${latest_url}"
  echo "${url}"
}
function download_mainsail_macros() {
  local ms_cfg_repo path  line gcode_dir
  path="${DATABK1}/config"
  status_msg "克隆 mainsail配置 ..."
  wget ${MAINSAIL_MACRO} -P "${path}";
  if ! grep -Eq "^\[include mainsail.cfg\]$" "${path}/printer.cfg"; then
    log_info "${path}/printer.cfg"
    sed -i "1 i [include mainsail.cfg]" "${path}/printer.cfg"
  fi
  line="$(($(grep -n "\[include mainsail.cfg\]" "${path}/printer.cfg" | tail -1 | cut -d: -f1) + 1))"
  gcode_dir="${DATABK1}/gcodes"
  if ! grep -Eq "^\[virtual_sdcard\]$" "${path}/mainsail.cfg"; then
      log_info "${path}/mainsail.cfg"
      sed -i "${line} i \[virtual_sdcard]\n path: ${gcode_dir}\n on_error_gcode: CANCEL_PRINT\n" "${path}/mainsail.cfg"
  fi
  #patch_mainsail_update_manager
  ok_msg "Done!"
}
function patch_mainsail_update_manager() {
  local conf="${DATABK1}/config/moonraker.conf"
  if ! grep -Eq "^\[update_manager mainsail\]\s*$" "${conf}"; then
    ### add new line to conf if it doesn't end with one
    [[ $(tail -c1 "${conf}" | wc -l) -eq 0 ]] && echo "" >> "${conf}"
    ### add Mainsails update manager section to moonraker.conf
    status_msg "将Mainsail添加到文件中的更新管理器:\n       ${conf}"
    /bin/sh -c "cat >> ${conf}" << MOONRAKER_CONF

[update_manager mainsail]
type: web
channel: stable
repo: mainsail-crew/mainsail
path: /home/print3D/mainsail
MOONRAKER_CONF
    fi
}
#===================================================#
#============== INSTALL KLIPPERSCREEN ==============#
#===================================================#
function klipperscreen_setup() {
  # 强制删除现有KlipperScreen目录
  [[ -d ${KLIPPERSCREEN_DIR} ]] && rm -rf "${KLIPPERSCREEN_DIR}"
  # 克隆到新的KlipperScreen目录
  if ! git clone "${KLIPPERSCREEN_REPO}" "${KLIPPERSCREEN_DIR}"; then
    print_error "克隆KlipperScreen从\n ${KLIPPERSCREEN_REPO}\n 失败!"
  fi
  status_msg "安装环境 ..."
  create_virtualenv "${KLIPPERSCREEN_ENV}" "${KLIPPERSCREEN_TXT}"
  modify_user
  update_x11
  #patch_klipperscreen_update_manager
  install_config_KlipperScreen
  add_desktop_file
  print_confirm "KlipperScreen安装完成!"
}
function modify_user()
{
  adduser  print3D  tty
  adduser  root  tty
}

function update_x11()
{
    if [ -e /etc/X11/Xwrapper.config ]
    then
       
        sed -i 's/allowed_users=console/allowed_users=anybody/g' /etc/X11/Xwrapper.config
    else
        
        echo 'allowed_users=anybody' |  tee /etc/X11/Xwrapper.config
    fi
}
function add_desktop_file()
{
    DESKTOP=$(<$KLIPPERSCREEN_DIR/scripts/KlipperScreen.desktop)
    mkdir -p $HOME/.local/share/applications/
    echo "$DESKTOP" | tee $HOME/.local/share/applications/KlipperScreen.desktop > /dev/null
}
function install_config_KlipperScreen(){
    DEFAULTS_FILE=/etc/default/KlipperScreen
        status_msg  "正在安装启动配置..."
        cat > ${DEFAULTS_FILE} <<EOF
    # Configuration for /etc/init.d/KlipperScreen
    KS_USER=root
    KS_EXEC="/bin/bash"
    KS_ARGS=" /etc/init.d/KlipperScreensh"

EOF
    chmod +x /root/print3D/ksdelay.sh
    chmod +x /etc/init.d/KlipperScreen
    chmod +x /etc/init.d/KlipperScreensh
    chmod 777 /root/print3D/ksdelay.sh
    chmod 777 /etc/init.d/KlipperScreen
    chmod 777 /etc/init.d/KlipperScreensh

}
function patch_klipperscreen_update_manager() {
  local conf="${DATABK1}/config/moonraker.conf"
  curl -o ${DATABK1}/config/KlipperScreen.conf -C - https://gitee.com/xiaoh5001/klipperocto4a/raw/master/scripts/KlipperScreen.conf
  sed -i "/trusted_clients:/a\    127.0.0.1" "${conf}" 
  if ! grep -Eq "^\[update_manager KlipperScreen\]\s*$" "${conf}"; then
      ### add new line to conf if it doesn't end with one
      [[ $(tail -c1 "${conf}" | wc -l) -eq 0 ]] && echo "" >> "${conf}"

      ### add KlipperScreens update manager section to moonraker.conf
      status_msg "正在添加KlipperScreen以更新文件中的管理器：\n       ${conf}"
      /bin/sh -c "cat >> ${conf}" << MOONRAKER_CONF

[update_manager KlipperScreen]
type: git_repo
path: /home/print3D/KlipperScreen
origin: https://gitee.com/Neko-vecter/KlipperScreen.git
env: /home/print3D/KlipperScreen-env/bin/python
requirements: scripts/KlipperScreen-requirements.txt
install_script: scripts/KlipperScreen-install.sh
MOONRAKER_CONF
  fi
}
#===================================================#
#============== INSTALL qd ==============#
#===================================================#
function octoklipper_install(){
  wget https://gitee.com/xiaoh5001/klipperocto4a/raw/master/scripts/KlipperScreen.conf   -O ${DATABK1}/config/KlipperScreen.conf 2>/dev/null
  wget https://gitee.com/xiaoh5001/klipperocto4a/raw/master/scripts/moonraker.conf  -O ${DATABK1}/config/moonraker.conf 2>/dev/null
  wget https://gitee.com/xiaoh5001/klipperocto4a/raw/master/scripts/printer.cfg  -O ${DATABK1}/config/printer.cfg 2>/dev/null 
  [[ -d /root/extensions/KlipperScreen} ]] && rm -rf /root/extensions/KlipperScreen
  mkdir -p /root/extensions/KlipperScreen
}

#================================================#
#============= MESSAGE FORMATTING ===============#
#================================================#
function create_virtualenv() {
  local ljm="${1}"
  local wjm="${2}"
  status_msg "正在安装$（“python3”-V）虚拟环境..."
  [[ -d ${ljm} ]] && rm -rf "${ljm}"
  if virtualenv -p "python3" "${ljm}"; then
    "${ljm}"/bin/pip install -U pip  setuptools -i "${PIP3YUAN}"
    "${ljm}"/bin/pip install -r "${wjm}" -i "${PIP3YUAN}"
  else
    sleep 2s
    sudo dpkg --configure -a
    if virtualenv -p "python3" "${ljm}"; then
        "${ljm}"/bin/pip install -U pip  setuptools -i "${PIP3YUAN}"
        "${ljm}"/bin/pip install -r "${wjm}" -i "${PIP3YUAN}"
    else
        log_error "创建python3环境时失败"
        error_msg "virtualenv创建失败！"
    fi
  fi
}
function select_msg() {
  echo -e "${white}   [➔] ${1}"
}
function status_msg() {
  echo -e "\n${magenta}###### ${1}${white}"
}
function ok_msg() {
  echo -e "${green}[✓ OK] ${1}${white}"
}
function warn_msg() {
  echo -e "${yellow}>>>>>> ${1}${white}"
}
function error_msg() {
  echo -e "${red}>>>>>> ${1}${white}"
}
function abort_msg() {
  echo -e "${red}<<<<<< ${1}${white}"
}
function title_msg() {
  echo -e "${cyan}${1}${white}"
}
function print_error() {
  [[ -z ${1} ]] && return

  echo -e "${red}"
  echo -e "#=======================================================#"
  echo -e " ${1} "
  echo -e "#=======================================================#"
  echo -e "${white}"
}
function print_confirm() {
  [[ -z ${1} ]] && return

  echo -e "${green}"
  echo -e "#=======================================================#"
  echo -e " ${1} "
  echo -e "#=======================================================#"
  echo -e "${white}"
}
function log_info() {
  local message="${1}" log="${LOGFILE}"
  echo -e "$(timestamp) [INFO]: ${message}" | tr -s " " >> "${log}"
}
function log_warning() {
  local message="${1}" log="${LOGFILE}"
  echo -e "$(timestamp) [WARN]: ${message}" | tr -s " " >> "${log}"
}
function log_error() {
  local message="${1}" log="${LOGFILE}"
  echo -e "$(timestamp) [ERR]: ${message}" | tr -s " " >> "${log}"
}
function timestamp() {
  date +"[%F %T]"
}
function report_status(){
    echo -e "\n\n###### $1"
}
status_msg "安装klipper！"
run_klipper_setup
status_msg "安装kmoonraker！"
moonraker_setup
status_msg "安装fluidd！"
install_fluidd
status_msg "安装mainsail！"
install_mainsail
status_msg "安装klipperscreen！"
klipperscreen_setup
status_msg "安装启动脚本！"
octoklipper_install
rm -rf /home/print3D/kiauh
status_msg "安装完成！"